/**
 * 对list.h的测试。
 */
#include <stdio.h>
#include <stdlib.h>

#include "test_tools.h"

static void list_baisc_test(void)
{
    /// 根据这个数组创建一个链表
    int array[16] = { 1, 9, 8, 4, 6, 17, 2, 31, 7, 5, 11, 21, 23, 99, 67, 59};
    int length = sizeof(array) / sizeof(int);
    struct list_head *head = LIST_FROM_ARRAY(array, length);
    struct list_head *pos = NULL;
    struct list_head *n = NULL;
    struct list_type *pos_type = NULL;
    struct list_type *n_type = NULL;
    /// 顺序创建
    DISPLAY_WHOLE_LIST(head);
    if (VALIDATE_WHOLE_LIST(head) != length) {
        LOG_TEST_FAIL("not all nodes valid\n");
    } else {
        LOG_TEST_PASS("all nodes are valid\n");
    }
    if (COMPARE_LIST_ARRAY(head, array) != length) {
        LOG_TEST_FAIL("not fully matched\n");
    } else {
        LOG_TEST_PASS("all matched\n");
    }

    /// 逆序创建
    struct list_head *head1 = malloc(sizeof(struct list_head));
    list_head_init(head1);
    for (int i = length-1; i >= 0; i--) {
        struct list_type *new_node = malloc(sizeof(struct list_type));
        list_head_init(&new_node->list_head);
        new_node->key = array[i];
        list_add(head1, &new_node->list_head);
    }
    printf("inv: ");
    DISPLAY_WHOLE_LIST(head1);
    if (VALIDATE_WHOLE_LIST(head1) != length) {
        LOG_TEST_FAIL("not all nodes valid\n");
    } else {
        LOG_TEST_PASS("all nodes are valid\n");
    }
    if (COMPARE_LIST_ARRAY(head1, array) != length) {
        LOG_TEST_FAIL("not fully matched\n");
    } else {
        LOG_TEST_PASS("all matched\n");
    }

    /// 测试普通逆序遍历
    int cnt = length - 1;
    list_foreach_inv(head, pos) {
        if (list_entry(pos, struct list_type, list_head)->key != array[cnt]) {
            break;
        }
        cnt--;
    }
    if (cnt != -1) {
        LOG_TEST_FAIL("list_foreach_inv failed! cnt: %d\n", cnt);
    } else {
        LOG_TEST_PASS("list_foreach_inv success! cnt: %d\n", cnt);
    }

    /// 测试加强顺序遍历
    cnt = 0;
    list_foreach_safe(head, pos, n) {
        if (list_entry(pos, struct list_type, list_head)->key != array[cnt]) {
            break;
        }
        cnt++;
    }
    if (cnt != length) {
        LOG_TEST_FAIL("list_foreach_safe failed! cnt: %d\n", cnt);
    } else {
        LOG_TEST_PASS("list_foreach_safe success! cnt: %d\n", cnt);
    }

    /// 测试加强逆序遍历
    cnt = length - 1;
    list_foreach_safe_inv(head, pos, n) {
        if (list_entry(pos, struct list_type, list_head)->key != array[cnt]) {
            break;
        }
        cnt--;
    }
    if (cnt != -1) {
        LOG_TEST_FAIL("list_foreach_inv failed! cnt: %d\n", cnt);
    } else {
        LOG_TEST_PASS("list_foreach_inv success! cnt: %d\n", cnt);
    }

    /// 测试加强版顺序入口遍历
    cnt = 0;
    list_foreach_entry_safe(head, pos_type, n_type, list_head) {
        if (pos_type->key != array[cnt]) {
            break;
        }
        cnt++;
    }
    if (cnt != length) {
        LOG_TEST_FAIL("list_foreach_entry_safe failed! cnt: %d\n", cnt);
        printf("\tpos_type: %p, n_type: %p\n", pos_type, n_type);
    } else {
        LOG_TEST_PASS("list_foreach_entry_safe success! cnt: %d\n", cnt);
    }

    /// 测试加强版逆序入口遍历
    cnt = length - 1;
    list_foreach_entry_safe_inv(head, pos_type, n_type, list_head) {
        if (pos_type->key != array[cnt]) {
            break;
        }
        cnt--;
    }
    if (cnt != -1) {
        LOG_TEST_FAIL("list_foreach_entry_safe_inv failed! cnt: %d\n", cnt);
        printf("\tpos_type: %p, n_type: %p\n", pos_type, n_type);
    } else {
        LOG_TEST_PASS("list_foreach_entry_safe_inv success! cnt: %d\n", cnt);
    }

    /// 删除部分节点和首个节点，并测试被删除的链表节点的有效性。
    int del_cnt = 0;
    int list_cnt = 0;
    int del_array1[5] = {0, 1, 5, 9, 11};
    int del_array1_len = sizeof(del_array1) / sizeof(int);
    int array1[sizeof(array) / sizeof(int)] = { 0 };
    cnt = 0;
    list_foreach_entry_safe(head, pos_type, n_type, list_head) {
        if (list_cnt == del_array1[del_cnt]) {
            list_del_init(&pos_type->list_head);
            /// 测试被删除的链表节点的有效性。
            if (LIST_NODE_VALIDATION(&pos_type->list_head) == 0) {
                LOG_TEST_PASS("list_del_init success!\n");
            } else {
                LOG_TEST_FAIL("list_del_init fail! "
                    "cnt: %d, key: %d, prev: %p, next: %p\n", 
                    cnt, 
                    pos_type->key, 
                    (pos_type->list_head).prev, 
                    (pos_type->list_head).next);
            }
            free(pos_type);
            del_cnt++;
        } else {
            array1[cnt] = pos_type->key;
            cnt++;
        }
        list_cnt++;
    }
    DISPLAY_WHOLE_LIST(head);
    if (VALIDATE_WHOLE_LIST(head) != cnt) {
        LOG_TEST_FAIL("not all nodes valid\n");
    } else {
        LOG_TEST_PASS("all nodes are valid\n");
    }
    if (COMPARE_LIST_ARRAY(head, array1) != cnt) {
        LOG_TEST_FAIL("not fully matched\n");
    } else {
        LOG_TEST_PASS("all matched\n");
    }

    /// 删除部分节点和末尾节点
    int del_array2[6] = {3, 6, 7, 12, 13, 0};
    int del_array2_len = sizeof(del_array2) / sizeof(int);
    del_array2[del_array2_len-1] = length-1;
    int array2[sizeof(array) / sizeof(int)] = { 0 };
    del_cnt = 0;
    list_cnt = 0;
    cnt = 0;
    list_foreach_entry_safe(head1, pos_type, n_type, list_head) {
        if (list_cnt == del_array2[del_cnt]) {
            list_del_init(&pos_type->list_head);
            free(pos_type);
            del_cnt++;
        } else {
            array2[cnt] = pos_type->key;
            cnt++;
        }
        list_cnt++;
    }
    DISPLAY_WHOLE_LIST(head1);
    if (VALIDATE_WHOLE_LIST(head1) != cnt) {
        LOG_TEST_FAIL("not all nodes valid\n");
    } else {
        LOG_TEST_PASS("all nodes are valid\n");
    }
    if (COMPARE_LIST_ARRAY(head1, array2) != cnt) {
        LOG_TEST_FAIL("not fully matched\n");
    } else {
        LOG_TEST_PASS("all matched\n");
    }

    /// 交换首节点和中间某个节点(5)
    cnt = 0;
    list_foreach(head, pos) {
        if (cnt == 5) {
            break;
        }
        cnt++;
    }
    n = list_first_node_safe(head);
    if (LIST_NODE_VALIDATION(n) != 0) {
        LOG_TEST_FAIL("get an invalid node from head! %p\n", n);
    } else {
        LOG_TEST_PASS("get a valid node from head!\n");
    }
    EXCHANGE_VALS(array1[0], array1[cnt]);
    list_exchange_nodes(n, pos);
    DISPLAY_WHOLE_LIST(head);
    if (VALIDATE_WHOLE_LIST(head) != (length - del_array1_len)) {
        LOG_TEST_FAIL("not all nodes valid\n");
    } else {
        LOG_TEST_PASS("all nodes are valid\n");
    }
    if (COMPARE_LIST_ARRAY(head, array1) != (length - del_array1_len)) {
        LOG_TEST_FAIL("not fully matched\n");
    } else {
        LOG_TEST_PASS("all matched\n");
    }


    /// 交换尾节点和中间某个节点(6)
    cnt = 0;
    list_foreach(head, pos) {
        if (cnt == 6) {
            break;
        }
        cnt++;
    }
    n = list_last_node_safe(head);
    if (LIST_NODE_VALIDATION(n) != 0) {
        LOG_TEST_FAIL("get an invalid node from head! %p\n", n);
    } else {
        LOG_TEST_PASS("get a valid node from head!\n");
    }
    EXCHANGE_VALS(array1[length-del_array1_len-1], array1[cnt]);
    list_exchange_nodes(n, pos);
    DISPLAY_WHOLE_LIST(head);
    if (VALIDATE_WHOLE_LIST(head) != (length - del_array1_len)) {
        LOG_TEST_FAIL("not all nodes valid\n");
    } else {
        LOG_TEST_PASS("all nodes are valid\n");
    }
    if (COMPARE_LIST_ARRAY(head, array1) != (length - del_array1_len)) {
        LOG_TEST_FAIL("not fully matched\n");
    } else {
        LOG_TEST_PASS("all matched\n");
    }

    /// 交换两个中间节点(3, 7)
    cnt = 0;
    list_cnt = 0;
    list_foreach(head, pos) {
        if (cnt == 3) {
            break;
        }
        cnt++;
    }
    list_foreach(head, n) {
        if (list_cnt == 7) {
            break;
        }
        list_cnt++;
    }
    list_exchange_nodes(n, pos);
    EXCHANGE_VALS(array1[list_cnt], array1[cnt]);
    DISPLAY_WHOLE_LIST(head);
    if (VALIDATE_WHOLE_LIST(head) != (length - del_array1_len)) {
        LOG_TEST_FAIL("not all nodes valid\n");
    } else {
        LOG_TEST_PASS("all nodes are valid\n");
    }
    if (COMPARE_LIST_ARRAY(head, array1) != (length - del_array1_len)) {
        LOG_TEST_FAIL("not fully matched\n");
    } else {
        LOG_TEST_PASS("all matched\n");
    }

    /// 交换首节点和尾某个节点
    n = list_first_node_safe(head);
    pos = list_last_node_safe(head);
    list_exchange_nodes(n, pos);
    EXCHANGE_VALS(array1[length-del_array1_len-1], array1[0]);
    DISPLAY_WHOLE_LIST(head);
    if (VALIDATE_WHOLE_LIST(head) != (length - del_array1_len)) {
        LOG_TEST_FAIL("not all nodes valid\n");
    } else {
        LOG_TEST_PASS("all nodes are valid\n");
    }
    if (COMPARE_LIST_ARRAY(head, array1) != (length - del_array1_len)) {
        LOG_TEST_FAIL("not fully matched\n");
    } else {
        LOG_TEST_PASS("all matched\n");
    }

    /// 结束测试前的清理工作
    DESTROY_WHOLE_LIST(head, struct list_type, list_head);
    DESTROY_WHOLE_LIST(head1, struct list_type, list_head);
}

void list_tests(void)
{
    printf("\n* list_test:\n");
    list_baisc_test();
}